package org.upfrost;

import static org.junit.Assert.*;

import java.util.Date;
import java.util.List;

import javax.sql.DataSource;

import junit.framework.Assert;


import org.junit.Test;
import org.upfrost.Mapper;
import org.upfrost.mapping.classes.TestClass2;
import org.upfrost.mapping.classes.TestClass3;

public class QueryTest extends BaseTestClass
{
	
	private class CustomMapper extends Mapper
	{
		static public final int UNSET_IDENTITY = 999999;

		public CustomMapper(DataSource dataSource) {
			super(dataSource);
		}

		// We add a special case where the identity value UNSET_IDENTITY is considered as UNSET,
		// but standard unset value (== 0) still return UNSET as well. In other words, if a key
		// gets this value, the mapper shall consider the key is not set, and should use a GeneratedValue
		// from the database (typically an autoincrement or a sequence)
		@Override
		public boolean isIdSet(Object keyValue) 
		{
			if (keyValue instanceof Integer && keyValue != null)
			{
				int val = ((Integer)keyValue).intValue();
				if (val == UNSET_IDENTITY)
					return false;
			}
			
			return super.isIdSet(keyValue);
		}
		
	}

	@Test
	public void testInsertIdNotGenerated()
	{
		Date nao = new Date();
		TestClass3 tc21 = new TestClass3();
		tc21.setId(100);
		tc21.setStrValue("value1");
		tc21.setSomeDate(nao);

		m_dao3.insert(tc21);
		
		createNewSession();
		TestClass3 tc22 = m_dao3.get(100);
		
		Assert.assertEquals(tc21, tc22);

		createNewSession();
		TestClass3 tc23 = m_dao3.get(100);
		Assert.assertEquals(tc21, tc23); // Two freshly loaded object with same id should be equals
		Assert.assertFalse(tc21 == tc23); // tc21 should not be in the cache, as it was written but not read
		Assert.assertTrue(tc22 == tc23); // Two freshly loaded object from the cache should be the same instance
	}

	@Test
	public void testInsertIdGenerated()
	{
		Date nao = new Date();
		TestClass2 tc21 = new TestClass2();
		tc21.setId(0);
		tc21.setStrValue("value1");
		tc21.setSomeDate(nao);
		m_dao2.insert(tc21);
		Assert.assertTrue(0 != tc21.getId()); // Id must be set
	}
	
	@Test
	public void testInsertIdGeneratedUnsetValue()
	{
		Date nao = new Date();
		TestClass2 tc21 = new TestClass2();
		tc21.setId(CustomMapper.UNSET_IDENTITY);
		tc21.setStrValue("value1");
		tc21.setSomeDate(nao);
		m_dao2.insert(tc21);
		Assert.assertTrue(0 != tc21.getId()); // Id must be set
	}

	@Test
	public void testUpdate()
	{
		TestClass2 tc21 = new TestClass2();
		tc21.setId(CustomMapper.UNSET_IDENTITY);
		tc21.setStrValue("value1");
		tc21.setSomeDate(new Date());
		m_dao2.insert(tc21);

		tc21.setStrValue("value2");
		m_dao2.update(tc21);
		
		TestClass2 tc22 = m_dao2.get(tc21.getId());
		Assert.assertEquals("value2", tc22.getStrValue());
		
		tc22.setStrValue("value3");
		tc22.setSomeDate(new Date());
		m_dao2.update(tc22);
		
		TestClass2 tc23 = m_dao2.get(tc21.getId());
		Assert.assertEquals("value3", tc22.getStrValue());
		Assert.assertEquals(tc22.getSomeDate(), tc22.getSomeDate());

		Assert.assertFalse(tc21.getStrValue().equals(tc22.getStrValue()));
	}

	@Test
	public void testSelect()
	{
		TestClass2 tc21 = new TestClass2();
		tc21.setId(CustomMapper.UNSET_IDENTITY);
		tc21.setStrValue("value1");
		tc21.setSomeDate(new Date());
		m_dao2.insert(tc21);

		TestClass2 tc22 = new TestClass2();
		tc22.setId(CustomMapper.UNSET_IDENTITY);
		tc22.setStrValue("value2");
		tc22.setSomeDate(new Date());
		m_dao2.insert(tc22);

		List<TestClass2> lst = m_dao2.createQuery("select * from test2 order by id desc").list();
		Assert.assertEquals(2, lst.size());
		
		Assert.assertNotSame(tc21, lst.get(1)); 
		Assert.assertEquals(tc21, lst.get(1)); 
		Assert.assertNotSame(tc22, lst.get(0));
		Assert.assertEquals(tc22, lst.get(0));
	}

	@Override
	protected Mapper createMapper(DataSource datasource) {
		return new CustomMapper(datasource);
	}

}
